import 'reflect-metadata'
// 参数装饰器
// 用于装饰类的构造函数或方法的参数
const REQUIRED_PARAMETERS = 'REQUIRED_PARAMETERS'
/**
 * 
 * @param target 装饰的目标对象，对于静态成员来说
 * @param propertyKey 参数所属的方法名称
 * @param parameterIndex 参数在参数列表中的索引 0
 */
function validate(target: any, propertyKey: string, parameterIndex: number) {
  const existingRequiredParameters: number[] = Reflect.getOwnMetadata(REQUIRED_PARAMETERS, target, propertyKey) || []
  existingRequiredParameters.push(parameterIndex)
  Reflect.defineMetadata(REQUIRED_PARAMETERS, existingRequiredParameters, target, propertyKey)
}
function validateParameters(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
  const originalMethod = descriptor.value
  descriptor.value = function(...args: any[]) {
    const existingRequiredParameters: number[] = Reflect.getOwnMetadata(REQUIRED_PARAMETERS, target, propertyKey) || []
    for(let parameterIndex of existingRequiredParameters) {
      if (args[parameterIndex] === undefined) {
        throw new Error(`Missing required arguments at position ${parameterIndex}`)
      }
    }
    return originalMethod.call(this, args)
  }
}
class User {
  constructor(private name: string) {

  }
  @validateParameters
  setName(@validate newName: string) {
    this.name = newName
  }
}
const user = new User('Alice')
// user.setName('Bob')
user.setName(undefined)